package com.xpec.c4.service.module.common;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ms.game.common.utility.xxx;
import com.ms.game.db.util.Utility;
import com.ms.game.gmtool.message.SGmtoolUpdateItemInfos;
import com.ms.game.invitefriend.bin.ItemInfo;
import com.ms.game.itembox.container.ItemBasic;
import com.ms.game.itembox.container.ItemBoxBin;
import com.ms.game.itembox.container.ItemJsonContent;
import com.ms.game.itembox.container.ItemTreasureBox;
import com.ms.game.itembox.db.ItemBoxModel;
import com.ms.game.itembox.db.ItemDAO;
import com.xpec.c4.game.system.InitData;
import com.xpec.c4.game.utility.GUIDFactory;
import com.xpec.c4.game.utility.GameUtility;


public class ItemInfoManager {
	
	private static final Log log = LogFactory.getLog(ItemInfoManager.class);
	
	public static final String ITEM_PACKAGE_NAME = "com.ms.game.itembox.container";
	
	public static final String DOT = ".";
	
	private static ItemInfoManager instance = new ItemInfoManager();
	
	public static ItemInfoManager getInstance(){
		return instance;
	}
	
	private ConcurrentHashMap<String, ItemBasic> itemBox = new ConcurrentHashMap<String, ItemBasic>();
	
	/**
	 * 是否正在更新道具資料
	 */
	private boolean isUpdateing;
	
	/**
	 * 同步鎖的物件
	 */
	private Object lockObject = new Object();
	
	private CommonModule commonModule;

	public ConcurrentHashMap<String, ItemBasic> getItemBox() {
		if(isUpdateing){
			synchronized (lockObject) {
				return itemBox;
			}
		}
		return itemBox;
	}

	public void setItemBox(ConcurrentHashMap<String, ItemBasic> itemBox) {
		this.itemBox = itemBox;
	}
	
	public boolean isUpdateing() {
		return isUpdateing;
	}

	public void setUpdateing(boolean isUpdateing) {
		this.isUpdateing = isUpdateing;
	}

	public void setCommonModule(CommonModule commonModule) {
		this.commonModule = commonModule;
	}
	
	public void updateItemBox(ItemBasic item , int type){
		synchronized (lockObject) {
			switch (type) {
			case SGmtoolUpdateItemInfos.INSERT:
			case SGmtoolUpdateItemInfos.MODIFY: {
				this.itemBox.put(item.getItemId(), item);
				break;
			}
			case SGmtoolUpdateItemInfos.DELETE: {
				this.itemBox.remove(item.getItemId());
				break;
			}
			}
			
//			System.err.println(GameUtility.getCurMethodName() + new GsonBuilder().create().toJson(itemBox));
			isUpdateing = false;
		}


		
	}
	
	public void updateItemBox(ConcurrentHashMap<String, ItemBasic> newItemBox){
		synchronized (lockObject) {
			this.itemBox = newItemBox;
			isUpdateing = false;
		}
//		System.err.println(new GsonBuilder().create().toJson(itemBox));
	}
	
	public static void main(String[] args) {
		
		System.setProperty("log4j.configurationFile", "./config/log4j2.xml");
		InitData.initAll();
		GUIDFactory.setWorldId(1);
		GUIDFactory.setProcessId(1);
		ItemInfoManager.getInstance().initItemBox();
		xxx.nothing();
//		ArrayList<ItemInfo> infos = new ArrayList<ItemInfo>();
//		
//		ItemInfo info = new ItemInfo();
//		info.setItemId("anime2");
//		info.setCount(10);
//		infos.add(info);
//		info = new ItemInfo();
//		info.setItemId("GOLDCOIN_01");
//		info.setCount(1);
//		infos.add(info);
//		info = new ItemInfo();
//		info.setItemId("SILENT_01");
//		info.setCount(5);
//		infos.add(info);
//		String aaaString = new Gson().toJson(infos);
//		ItemTreasureBox card = (ItemTreasureBox)ItemInfoManager.getInstance().getItemBox().get("LEVEL_BOX_LV1");
		
		xxx.nothing();
	}
	
	public static Class<?> getItemClassbyClassName(String className) throws ClassNotFoundException{
		Class<?> instanceClass = Class.forName(ITEM_PACKAGE_NAME + DOT + className);
		return instanceClass;
	}
	
	public void initItemBox() {
		this.itemBox = getNewItemBox();
	}
	
	public ConcurrentHashMap<String, ItemBasic> getNewItemBox(){
	
		ArrayList<String> itemBoxFieldNames = getItemBoxModelFieldNames();
		
		ConcurrentHashMap<String, ItemBasic> itemBoxMap = new ConcurrentHashMap<String, ItemBasic>();
		
		ArrayList<ItemBoxModel> itemModels = ItemDAO.getAllItems();
		try {
			for (ItemBoxModel model : itemModels) {
				
				ItemBasic item = reflectionItemBoxModel(model, itemBoxFieldNames);
				// 放到itembox
				itemBoxMap.put(model.getItemId(), item);
			}

		} catch (Exception e) {
			if (log.isErrorEnabled()) {
				log.error(GameUtility.getCurMethodName() + "Init ItemBox Fail!", e);
			}
		}
		 
		return itemBoxMap;
	}
	
	/**
	 * 取得itemBoxModel所有欄位
	 * @return
	 */
	public static ArrayList<String> getItemBoxModelFieldNames(){
		ArrayList<String> itemBoxFields = new ArrayList<String>();
		for (Field field : ItemBoxModel.class.getDeclaredFields()) {
			itemBoxFields.add(field.getName());
		}
		return itemBoxFields ;
	}

	public static ItemBasic reflectionItemBoxModel(ItemBoxModel itemBoxModel, ArrayList<String> itemBoxModelFieldNames) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException, IllegalArgumentException {
		// 組出className
		Class<?> instanceClass = Class.forName(ITEM_PACKAGE_NAME + DOT + itemBoxModel.getItemClassName());

		Object item = instanceClass.newInstance();

		Field[] fields = Utility.getAllFieldToCache(item.getClass());
		
		for (Field field : fields) {
			if (itemBoxModelFieldNames.contains(field.getName())) {
				setField(itemBoxModel, item, field);
			}
		}
		


		return (ItemBasic) item;
	}
	
	private static void setDeclaredField(Object from, Object to,Class<?> toClazz,String fieldName) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
			Field valueField = from.getClass().getDeclaredField(fieldName);
			valueField.setAccessible(true);
			Object value = valueField.get(from);
			Field toField = toClazz.getDeclaredField(fieldName);
			toField.setAccessible(true);
			toField.set(to, value);
	}
	
	private static void setField(Object from, Object to, Field field) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
		Field valueField = from.getClass().getDeclaredField(field.getName());
		valueField.setAccessible(true);
		Object value = valueField.get(from);
		field.setAccessible(true);
		field.set(to, value);
		
		xxx.nothing();
}
	
	
	/**
	 * 取得指定的道具
	 * 
	 * @param itemId
	 *            道具id
	 * @return 道具資料
	 */
	public ItemBasic getItem(String itemId) {
		ConcurrentHashMap<String, ItemBasic> itemBox = getItemBox();
		if(itemBox.containsKey(itemId)){
			return getItemBox().get(itemId);
		}
		return null;
	}

	/**
	 * 確認道具是否存在
	 * 
	 * @param itemId
	 *            item id
	 * @return 存在: true<br>
	 *         不存在: false
	 */
	public boolean isItemExist(String itemId) {
		if(getItemBox().containsKey(itemId) && getItemBox().get(itemId) != null){
			return true;
		}
		return false;
	}
	
	/**
	 * 檢查道具清單內的道具 id 是否存在於 {@link ItemBoxBin}
	 * 
	 * @param itemList
	 *            道具清單
	 */
	public void verifyItemList(ArrayList<ItemInfo> itemList) {

		if (getItemBox() == null) {
			return;
		}

		if (itemList == null) {
			return;
		}

		for (ItemInfo info : itemList) {
			String itemId = info.getItemId();
			if (!isItemExist(itemId)) {
				if (log.isErrorEnabled()) {
					log.error("item [" + itemId + "] is not exist in itemBox");
				}
			}
		}
	}
	
	/**
	 * 檢查道具是否能被精煉
	 * 
	 * @param itemBin
	 *            道具數據資料
	 * @return
	 */
	public boolean isItemCanRefine(ItemBasic itemBin) {
		if (itemBin == null) {
			return false;
		}
		
		if(!itemBin.isCanRefine()){
			return false;
		}
		
		// 精煉資訊列表為 0 就是不能精煉
		if (GameUtility.getArrayListSize(itemBin.getRefineCrystalCostList()) == 0) {
			return false;
		}

		return true;
	}
	
	public static final int GET_NEED_CRYSTAL_FAIL = -1;
	
	/**
	 * 取得精煉到下一級需要的水晶數量
	 * 
	 * @param currentLevel
	 *            目前精煉等級
	 * @param itemBin
	 *            道具數據
	 * @return 成功: 需要的水晶數量<br>
	 *         失敗: {@link #GET_NEED_CRYSTAL_FAIL}
	 */
	public int getRefineNeedCrystal(int currentLevel, ItemBasic itemBin) {
		if (itemBin == null) {
			return GET_NEED_CRYSTAL_FAIL;
		}
		
		// 不能精煉
		int refineLevelCount = GameUtility.getArrayListSize(itemBin.getRefineCrystalCostList());
		if (refineLevelCount == 0) {
			return GET_NEED_CRYSTAL_FAIL;
		}

		if (currentLevel < 0) {
			return GET_NEED_CRYSTAL_FAIL;
		}

		// 超過最高等級
		if (currentLevel >= refineLevelCount) {
			return GET_NEED_CRYSTAL_FAIL;
		}

		// 取得精煉需要的數量
		int refineCrystalCost = itemBin.getRefineCrystalCostList().get(currentLevel);

		return refineCrystalCost;
	}
	
	/**
	 * 道具精煉期過了沒有
	 * 
	 * @param itemRefineEndTime
	 *            道具上記錄的過期時間
	 * @param currentTime
	 *            目前時間
	 * @return
	 */
	public boolean isRefineTimeExpire(long itemRefineEndTime, long currentTime) {
		if (itemRefineEndTime > 0) {
			if (currentTime > itemRefineEndTime) {
				return true;
			}
		}

		return false;
	}
	
	public void checkItemExist() {
		
		
		HashMap<String, ArrayList<String>> bonusPackNotExistItem = new HashMap<String, ArrayList<String>>();
		
		HashMap<String, ArrayList<String>> treasureBoxNotExistItem = new HashMap<String, ArrayList<String>>();
		//先檢查
		for (ItemBasic itemBasic : itemBox.values()) {

			if(itemBasic.isTreasureBox()){
				
				ItemTreasureBox treasureBox = (ItemTreasureBox)itemBasic;
				String treasureBoxId = treasureBox.getItemId();
				for (ItemJsonContent content : treasureBox.getFixItemList()) {
					String itemId = content.getItemId();
					boolean isExist = isItemExist(itemId);
					if(!isExist){
						if(!treasureBoxNotExistItem.containsKey(treasureBoxId)){
							ArrayList<String> items = new ArrayList<String>();
							items.add(itemId);
							bonusPackNotExistItem.put(treasureBoxId, items);
							continue;
						}
						
						ArrayList<String> items = bonusPackNotExistItem.get(treasureBoxId);
						items.add(itemId);
					}
				} 
			}

		}
		
		
		boolean needShotDown = false;
		if(bonusPackNotExistItem.size() > 0){
			StringBuilder builder = new StringBuilder();
			builder.append("Bonus Pack Miss Item ");
			for (Entry<String, ArrayList<String>> missItems : bonusPackNotExistItem.entrySet()) {
				builder.append(missItems.getKey());
				builder.append(":");
				
				for (String itemId : missItems.getValue()) {
					builder.append(itemId);
					builder.append(",");
				}
				
				builder.deleteCharAt(builder.length() - 1);
				builder.append(" | ");
			}

			if(log.isErrorEnabled()){
				log.error(builder.toString());
			}
			
			needShotDown= true;
		}
		
		if(treasureBoxNotExistItem.size() > 0){
			StringBuilder builder = new StringBuilder();
			builder.append("Treasure Box Not Exist Item : ");
			for (Entry<String, ArrayList<String>> missItems : treasureBoxNotExistItem.entrySet()) {
				builder.append(missItems.getKey());
				builder.append(":");
				
				for (String itemId : missItems.getValue()) {
					builder.append(itemId);
					builder.append(",");
				}
				
				builder.deleteCharAt(builder.length() - 1);
				builder.append(" | ");
			}

			if(log.isErrorEnabled()){
				log.error(builder.toString());
			}
			
			needShotDown= true;
		}
		
		if(needShotDown){
			throw new RuntimeException();
		}
	}

}
